# -*- coding: utf-8 -*-
from BeautifulSoup import BeautifulSoup, Comment
import sys
import urllib2
from urllib2 import URLError, HTTPError
import re
import logging
import time

stdin = sys.stdin
stdout = sys.stdout
reload(sys)
sys.setdefaultencoding('utf-8')
sys.stdin = stdin
sys.stdout = stdout

from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import urlfetch

"""
DMM APIを使って商品情報を取得する
"""
class Dmm:
    def __init__(self, api_id, affiliate_id):
        """コンストラクタ"""
        self.baseurl = "http://affiliate-api.dmm.com/"
        self.proxy_host = None
        self.proxy_port = None
        self.api_id = api_id
        self.affiliate_id = affiliate_id
        self.version = "1.0.0"
        self.site = 'DMM.co.jp'
        self.service = 'digital'
        self.operation = 'ItemList'

        self.url = None

    def setProxy(self, host, port=8080):
        """プロキシをセット"""
        self.proxy_host = host
        self.proxy_port = port

    def setVersion(self, version):
        """バージョンをセット"""
        self.version = version
    def setSite(self, site):
        """Siteをセット"""
        self.site = site
    def setService(self, service):
        """Serviceをセット"""
        self.service = service

    def keywordSearch(self, keyword, **options):
        """アイテムを検索"""
        params = options
        params["keyword"] = keyword
        return unicode(self.sendRequest(params),'euc-jp')
        #return self.buildURL(params)

    def buildURL(self, params):
        """RESTリクエストのURLアドレスを構築"""
        params["api_id"] = self.api_id
        params["affiliate_id"] = self.affiliate_id
        params["version"] = self.version
        params["site"] = self.site
        params["service"] = self.service
        params["operation"] = self.operation
        params["timestamp"] = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
        sorted_params = sorted(params.items())

        # paramsのハッシュを展開
        request = []
        for p in sorted_params:
            pair = "%s=%s" % (p[0], urllib2.quote(p[1].encode("euc-jp")))
            request.append(pair)

        url = self.baseurl + "?" + "&".join(request)

        return url

    def sendRequest(self, params):
        """DMMにリクエストを送付し、取得したXMLを返す"""
        self.url = self.buildURL(params)
        logging.debug(self.url)
        
        if self.proxy_host:
            proxy_handler = urllib2.ProxyHandler({"http":"http://%s:%s/" % (self.proxy_host, self.proxy_port)})
            opener = urllib2.build_opener(proxy_handler)
        else:
            opener = urllib2.build_opener()
        return opener.open(self.url).read()

    def parseXML(self, s):
        from BeautifulSoup import BeautifulStoneSoup
        dic = {}
        xdoc = BeautifulStoneSoup(s)
        logging.debug(xdoc)
        it = xdoc.findAll('item')
#        print len(it)
        if len(it) > 0:
            dic['発売日'] =  it[0].date.contents[0].string
            dic['出演者'] =  it[0].actress.contents[1].string
            dic['シリーズ'] =  it[0].series.contents[1].string
            dic['メーカー'] =  it[0].maker.contents[1].string
            dic['レーベル'] =  it[0].label.contents[1].string
            dic['価格'] =  it[0].price.contents[0].string
        else:
            return False

        return it[0].title.string, it[0].imageurl.small.string, dic

def searchDMMapi(keyword):
    apikey = 'R5t7eL5qCZkhk5wQvF6S'
    affiid = 'sixapart-990'
    dmm = Dmm(apikey, affiid)
    s = dmm.keywordSearch(keyword,hits='1')
    dic = dmm.parseXML(s)
    return dic

def searchAPI(self, keyword, url, affid):
    title , imgurl, dic = searchDMMapi(keyword)
    info = []
    for k, v in dic.items():
        l =  k + '：' + v
        info.append(l)

    logging.debug( info )
    renderBox(self, url, title, imgurl, info, affid)
    
def mainQuery(self, url, affid):

    try:
        result = urlfetch.fetch(url=url, method=urlfetch.GET, deadline=10)
        if result.status_code == 200:
            allLines = result.content
        else:
            logging.error(":200 e.code:%s", result.status_code)
            return False
            
#        allLines = urllib2.urlopen(url).read()
    except urlfetch.DownloadError, e:
        logging.debug("Download Error")
        time.sleep(1)
        r = mainQuery(url, affid)
        return r
    
    except HTTPError, e:
        logging.error("e.code:%s", e.code)
        logging.error("e.read:%s", e.read)
        if e.code == 503:
            time.sleep(1)
            r = mainQuery(url, affid)
            return r
        else:
            return False
    except URLError, e:
        logging.error("e.code:%s", e.code)
        logging.error("e.read:%s", e.read)
        time.sleep(1)
        r = mainQuery(url, affid)
        return r

    parseHtml(self, url, allLines, affid)

def parseHtmlSub(self, url, s, t, affid):
    cid = ''
    info = []
    infoTmp = []
    
    r = re.match(r'http://www.dmm.co.+/.+/-/detail/=/cid=(.+?)/', url)
    if r:
        cid = r.group(1)
        if s.find('span', id="title-" + cid):
            title = s.find('span', id="title-" + cid).string
        elif s.find('span', id="title-" + cid + 'r'):
            title = s.find('span', id="title-" + cid + 'r').string
        elif s.find('h1', id="title"):
            title = s.find('h1', id="title").string
        else:
            title = s.title.string
        logging.debug(title)
#        rtnXML = searchDMMapi(cid)
#        logging.debug(rtnXML)
        imgcid = 'package-src-' + cid
    else:
        logging.error("対応していないページのタイプです。そのうち修正されるかもしれません")
        self.response.out.write("対応していないページのタイプです。そのうち修正されるかもしれません")
        return
        
    if s.find('table', {'class':'float-l mg-b20'}):
        tr = s.find('table', {'class':'float-l mg-b20'}).findAll('tr')
    elif s.find('table', {'class':'mg-b20'}):
        tr = s.find('table', {'class':'mg-b20'}).findAll('tr')
    elif s.find('dl', {'class':'set-list'}):
        logging.error("セットレンタルには対応していません。そのうち修正されるかもしれません")
        self.response.out.write("セットレンタルには対応していません。そのうち修正されるかもしれません<br>セットレンタルはアフェリエイトの対象になるかの判定がイマイチ不明なので、ここの商品へのリンクがおすすめです")
        return
    else:
        logging.error("except:対応していないページのタイプです。そのうち修正されるかもしれません")
        self.response.out.write("対応していないページのタイプです。そのうち修正されるかもしれません")
        return

    prog = re.compile(r'^[ \-\n(&nbsp;)]+$')
    maxLine = 7

    for i in tr:
        td = i.findAll('td')
        if len(td) > 1:
#            logging.error(td[1])
            col1 = td[0].string
            if td[1].find('img'):
                col2 = td[1].prettify().replace('<br />', '').replace('\n', '')
                if td[1].find('a', id='tdmmTweet'):
                    continue
            else:
#                col2 = td[1].findAll(text=lambda text:isinstance(text, Comment))
                if td[1].find('script'):
                    td[1].find('script').extract()

#                logging.error(td[1])
                lineTmp = []
                for line in td[1].findAll(text=True):
                    if not prog.match(line):
#                    if line != '\n' and line != '\n----' and line != '----' and line != '\n----\n' and line != '----\n':
                        lineTmp.append(line)

                col2 = (','.join(lineTmp)).replace('\n', '')
            if col1 != '' and col2 != '':
                logging.debug(str(col1) + str(col2))
                infoTmp.append(str(col1) + str(col2))
            if len(infoTmp) > maxLine:
                break

    if t:
        for i in infoTmp:
            for j in t:
                if i.find(j) == 0:
                    info.append(i)
    else:
        info = infoTmp[0:maxLine]
                  
    if (s.find(text=u"平均評価：")):
        score =  str(s.find(text=u"平均評価：").parent.nextSibling.nextSibling.find('img'))
        info.append("平均評価：" + score)

    if s.find('div', id="sample-video") != None:
        imgUrl = s.find('div', id="sample-video").find('img')['src']
    elif s.find('img', id=re.compile('^' + imgcid + '[a-z]*$')) != None:
#    elif s.find('img', id=imgcid) != None:
        imgUrl = s.find('img', id=re.compile('^' + imgcid + '[a-z]*$'))['src']
#        imgUrl = s.find('img', id=imgcid)['src']
#    elif url.find('http://www.dmm.co.jp/digital/') == 0:
#        imgUrl = 'http://pics.dmm.co.jp/digital/cg/' + cid + '/' + cid + 'pt.jpg'
#    elif url.find('http://www.dmm.co.jp/digital/videoc/') == 0: #素人動画
#        imgUrl =  s.find('div', id="sample-video").find('img')['src'].replace('jp.jpg', 'js.jpg')
    else:
#        r = re.match(r'http://www.dmm.co.jp/.+/-/detail/=/cid=(.+)/', url)
#        cid = r.group(1)
        logging.error("parseHtmlSub can't get image:" + url)
        imgUrl = 'http://pics.dmm.co.jp/' + cid + '/' + cid + 'ps.jpg'
        
    renderBox(self, url, title, imgUrl, info, affid)
        
def parseHtml(self, url, allLines, affid):
    t = []

    s = BeautifulSoup(allLines, fromEncoding="euc-jp")

    if s.originalEncoding == 'windows-1252':
        allLines = allLines.decode('euc-jp', 'ignore').encode('utf-8')
        s = BeautifulSoup(allLines, fromEncoding="utf-8")
        if s.originalEncoding == 'windows-1252':
            logging.error("Unrecovered Encoding Error:%s URL:", s.originalEncoding, url)
            return

    n = url.find('http://www.dmm.co.jp/digital/videoa/')
    logging.debug(n)
    if url.find('http://www.dmm.co.jp/digital/videoa/') == 0: #18動画
        r = re.match(r'http://www.dmm.co.+/.+/-/detail/=/cid=(.+?)/', url)
        if r:
            cid = r.group(1)
            searchAPI(self, cid, url, affid)
    else:
        parseHtmlSub(self, url, s, t, affid)

#    if url.find('http://www.dmm.co.jp/mono/dvd/') == 0: #18禁DVD
#        t = [u'出演者：', u'発売日：', u'メーカー：', u'レーベル：', u'収録時間：', u'ジャンル：']
#        imgDir = 'mono/movie/'
#    if url.find('http://www.dmm.co.jp/mono/anime/') == 0: #18禁アニメDVD
#        t = [u'発売日：', u'シリーズ：', u'メーカー：', u'レーベル：']
#        imgDir = 'mono/movie/'
#    elif url.find('http://www.dmm.co.jp/mono/pcgame/') == 0: #PCゲーム
#        t = [u'発売日：', u'ブランド：', u'ゲームジャンル：', u'原画：', u'ボイス：']
#        imgDir = 'mono/game/'
#    else:
#    return


def renderBox(self, url, title, imgUrl, info, affid):

    powerd = False

    html = """
<html>
<head>
<title>dmmlet 検索結果</title>
<link rel="stylesheet" type="text/css" href="http://dmmlet.googlecode.com/svn/trunk/styles.css" />
<script type="text/javascript">
function clip_copy(id) {
  var area = document.getElementById(id);
  if (document.all && navigator.userAgent.match(/windows/i) && area.value) {
    copy_obj = area.createTextRange();
    copy_obj.execCommand("Copy");
    alert("クリップボードにコピーしました。");
  }
}
</script>
</head>
<body>

<div id="head"></div>

<div id="container">
<h2 class="result-head">リンクを作る</h2>

<p class="description">好みのHTMLをコピーして記事に貼り付けてください。アソシエイト・リンクが作成されます。</p>
"""
    if imgUrl != '':
        html += '<h3>商品情報リンク (レビューあり)</h3><br>'
        html1 = '<div class="dmmlet-box" style="margin-bottom:0px;"><div class="dmmlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="' + url + affid + '" name="dmmletlink" target="_blank"><img src="' + imgUrl + '" alt="' + title + '" style="border: none;" /></a></div><div class="dmmlet-info" style="line-height:120%; margin-bottom: 10px"><div class="dmmlet-name" style="font-size:120%;margin-bottom:10px;line-height:120%"><a href="' + url + affid + '" name="dmmletlink" target="_blank">' + title + '</a>'
        if powerd:
            html1 += '<div class="dmmlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/browse/ASIN/B00486UR2I//ref=nosim/" title="' + title + '" target="_blank">dmmlet</a> at 11.02.02</div>'
        html1 += '</div><div class="dmmlet-detail" style="margin-top: 20px">'

        for i in info:
            html1 += i + '<br />'
        html1 += '</div></div></div>'
#        html1 += '</div><div class="dmmlet-sub-info" style="float: left;"><div class="dmmlet-link" style="margin-top: 5px"><a href="' + url + affid + '" name="dmmletlink" target="_blank">dmm.com で詳細を見る</a></div></div></div><div class="dmmlet-footer" style="clear: left"></div></div>'

        html += html1
        html += """
<textarea cols="40" rows="2" id="standard" name="code" onclick="this.focus();this.select()">"""
        html += html1
        html += """
</textarea>
<br />
<input type="button" onClick="clip_copy('standard')" value="コピー ( IEのみ )" />
"""
    html += '<h3>テキストリンク</h3><br>'
    html2 = '<div class="dmmlet-info" style="line-height:120%; margin-bottom: 10px"><div class="dmmlet-name" style="font-size:120%;margin-bottom:10px;line-height:120%"><a href="' + url + affid + '" name="dmmletlink" target="_blank">' + title + '</a></div></div><br />'

    html += html2
    html += """
<textarea cols="40" rows="2" id="textlink" name="code" onclick="this.focus();this.select()">"""
    html += html2
    html += """
</textarea>
<br />
<input type="button" onClick="clip_copy('textlink')" value="コピー ( IEのみ )" />
"""

    if imgUrl != '':
        html += '<h3>イメージリンク</h3><br>'
        html3 = '<div class="dmmlet-box" style="margin-bottom:0px;"><div class="dmmlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="' + url + affid + '" name="dmmletlink" target="_blank"><img src="' + imgUrl + '" alt="' + title + '" style="border: none;" /></a></div>'
        html += html3
        html += """
<textarea cols="40" rows="2" id="imagelink" name="code" onclick="this.focus();this.select()">
"""
        html += html3
        html += """
</textarea>
<br />
<input type="button" onclick="clip_copy('imagelink')" value="コピー ( IEのみ )" />
"""
    html += """
</div>
</div>
</body>
</html>
"""

    self.response.out.write(html)

def indexOut(self):
    html = """
<head>
<title>dmmletツール</title>
<link rel="stylesheet" type="text/css" href="http://dmmlet.googlecode.com/svn/trunk/styles.css" />
</head>
<body>
<div id="container">

<div class="home">

<h1>dmmlet</h1>
<p class="introduction"><strong>dmmlet</strong>は<a href="http://www.dmm.co.jp/sizapart-001" target="_blank">dmm.co.jp</a>のアフィリエイトを手軽にするツールです</p>
<p>名前からも分かるように、<div><a href="http://app.bloghackers.net/amazlet/" target="_blank">amazletツール</a></div>を完全に模倣しています。
そっちの方が使いやすいかなと思いまして。覚える作業も少なくて済みますし。
検索機能が無いのが本家との違いです。<br />
※まだ対応していないコーナーも多いですが、そのうち対応するかもしれません。
</p>
<p>こんにちは<span class="guest">ゲスト</span>さん<br />
あなた専用の dmmletツールを <a href="?__mode=setup">セットアップ</a> しましょう</p>

</div>

<div class="hint">
ヒント: dmmletツールの使い方は
<li>dmm.co.jp の個別商品ページで<strong>ブックマークからワンクリック</strong>でアソシエイト・リンクを作成</li>
</div>

<div class="footer-menu-mini">「セットアップしたのにゲストになってしまう」<br /> ブックマークから起動していますか?</div>
<br>
<div class="hint">
  上手くいかない場合、手動でアフェリエイトリンクを作成できます
  <form name="form" action="http://dmmbookmarklet.appspot.com/" method="get">
<div class="label">アソシエイトIDを入力: (例) sixaprat-001</div>
<input type="text" name="affiliate_id" value="" />
<div class="label">商品ページのURL: (例) http://www.dmm.co.jp/digital/videoa/-/detail/=/cid=2wss00159/</div>
<input type="text" name="url" size="80" value="" /><br>
<input type="submit" value="表示" />
<input type="hidden" name="__mode" value="urlsearch" />
</form>
</div>

</div>

<div id="footer">
<iframe src="http://affili.dmm.com/cont/autocm.php?a=sixapart-001&b=3&c=19&d=1&e=12"marginwidth="0" marginheight="0" width="728" height="90" border="0" frameborder="0" style="border:none;" scrolling="no"></iframe>
<div class="footer-menu" style="margin-bottom: 5pt;">お買い物、アフィリエイトも <a href="http://www.dmm.co.jp/sixapart-001" target="_blank">dmm.co.jp</a></div>
</div>
</body>
</html>
"""
    self.response.out.write(html)

def setupOut(self):
    html = """
<html>
<head>
<title>amazletツールセットアップ</title>
<link rel="stylesheet" type="text/css" href="http://dmmlet.googlecode.com/svn/trunk/styles.css" />
<script type="text/javascript">
function validate (obj) {
  if (obj.value == "") {
    window.alert("値を入力してください。")
    return false;
  }
  return true;
}
function key_validate (obj) {
   if (event.keyCode == 13) {
     return validate(obj);
   }
}
</script>
<body>

<div id="head"></div>

<div id="container">
<h1>dmmlet</h1>
<h2>dmmletツールのセットアップ</h2>

<p>dmmletツールをセットアップすると、dmmletツールで作成したリンクのアソシエイトIDがあなたのIDになり、Amazon商品の紹介料があなたに還元されるようになります。</p>

<p class="description">セットアップを行うには、まず以下のボックスにdmmアソシエイトIDを入力してください。</p>

<form name="form" method="get">
<div class="label">アソシエイトIDを入力: (例) dmm-001</div>
<input type="text" name="affiliate_id" onkeydown="var bool = key_validate(this); return bool" value="" /> <input type="submit" onclick="var bool = validate(form.affiliate_id); return bool;" value="次へ" />
<input type="hidden" name="__mode" value="showcode" />
</form>

</div>

</body>
</html>
"""
    self.response.out.write(html)

def showcodeOut(self, code):
    html = """
<html>
<head>
<title>dmmletツール セットアップ</title>
<link rel="stylesheet" type="text/css" href="http://dmmlet.googlecode.com/svn/trunk/styles.css" />
</head>
<body>

<div id="head"></div>

<div id="container">
<h1>dmmlet</h1>

<h2>dmmletツールをドラッグ</h2>

<p class="description">以下のリンクをブラウザのリンクか、お気に入りにドラッグすればセットアップ完了です。(一部のブラウザでは警告が出ますが、無視して大丈夫です。)</p>

<p>※ドラッグできない場合は、右クリックでお気に入りに追加してください。</p>

<div class="bm-code"><a href="javascript:var%20afid='
"""
    html += code
    html += """
';var%20u=document.location.href;javascript:void(window.open('http://dmmbookmarklet.appspot.com/?__mode=urlsearch&affiliate_id=' + afid + '&url='+u,'_blank','width=440,height=600,resizable=1,scrollbars=1,status=1'))">dmmlet it!</a></div>

<p>セットアップが完了したら、dmm の個別商品のページに行ってブックマークの「dmmlet it!」をクリックしましょう。</p>

<div id="button-menu">
<input type="button" onclick="javascript:window.close()" value="ウィンドウを閉じる" />
</div>

</div>
</html>
"""
    self.response.out.write(html)

class MainPage(webapp.RequestHandler):

    def get(self):
        mode = self.request.get('__mode')
        affid = self.request.get('affiliate_id')
        url = self.request.get('url')
#        url = urllib.unquote_plus(url)
        
        if mode == 'setup':
            setupOut(self)
        elif mode == 'showcode':
            showcodeOut(self, affid)
        elif mode == 'urlsearch' and url.find('http://www.dmm.co') == 0:
            logging.debug(url)
            mainQuery(self, url, affid)
        elif mode == 'urlsearch':
#            self.response.clear()
            self.redirect("http://dmmlet.googlecode.com/svn/trunk/warning.html")
            logging.error('location to warning')
        else:
            indexOut(self)

application = webapp.WSGIApplication(
    [('/', MainPage)],
    )
#    debug=False)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
